# TODO: Add comment
# 
# Author: srazbash
###############################################################################

unParameteriseTBATS<-function(param.vector, control) {
	#print(control)
	if(control$use.box.cox) {
		lambda<-param.vector[1]
		alpha<-param.vector[2]
		if(control$use.beta) {
			if(control$use.damping) {
				small.phi<-param.vector[3]
				beta<-param.vector[4]
				gamma.start<-5
			} else {
				small.phi<-1
				beta<-param.vector[3]
				gamma.start<-4
			}
		} else {
			small.phi<-NULL
			beta<-NULL
			gamma.start<-3
		}
		if(control$length.gamma > 0) {
			gamma.one.vector<-param.vector[gamma.start:(gamma.start+(control$length.gamma/2)-1)]
			gamma.two.vector<-param.vector[(gamma.start+(control$length.gamma/2)):(gamma.start+(control$length.gamma)-1)]
			final.gamma.pos<-gamma.start+control$length.gamma-1
		} else {
			gamma.one.vector<-NULL
			gamma.two.vector<-NULL
			final.gamma.pos<-gamma.start-1
		}
		if(control$p != 0) {
			ar.coefs<-param.vector[(final.gamma.pos+1):(final.gamma.pos+control$p)]
		} else {
			ar.coefs<-NULL
		}
		if(control$q != 0) {
			ma.coefs<-param.vector[(final.gamma.pos+control$p+1):length(param.vector)]
		} else {
			ma.coefs<-NULL
		}
	} else {
		lambda<-NULL
		alpha<-param.vector[1]
		if(control$use.beta) {
			if(control$use.damping) {
				small.phi<-param.vector[2]
				beta<-param.vector[3]
				gamma.start<-4
			} else {
				small.phi<-1
				beta<-param.vector[2]
				gamma.start<-3
			}
		} else {
			small.phi<-NULL
			beta<-NULL
			gamma.start<-2
		}
		if(control$length.gamma > 0) {
			gamma.one.vector<-param.vector[gamma.start:(gamma.start+(control$length.gamma/2)-1)]
			gamma.two.vector<-param.vector[(gamma.start+(control$length.gamma/2)):(gamma.start+(control$length.gamma)-1)]
			final.gamma.pos<-gamma.start+control$length.gamma-1
		} else {
			gamma.one.vector<-NULL
			gamma.two.vector<-NULL
			final.gamma.pos<-gamma.start-1
		}
		if(control$p != 0) {
			ar.coefs<-param.vector[(final.gamma.pos+1):(final.gamma.pos+control$p)]
		} else {
			ar.coefs<-NULL
		}
		if(control$q != 0) {
			ma.coefs<-param.vector[(final.gamma.pos+control$p+1):length(param.vector)]
		} else {
			ma.coefs<-NULL
		}
	}
	return(list(lambda=lambda, alpha=alpha, beta=beta, small.phi=small.phi, gamma.one.v=gamma.one.vector, gamma.two.v=gamma.two.vector, ar.coefs=ar.coefs, ma.coefs=ma.coefs))
}

makeParscale<-function(control) {
	#print(control)
	if(control$use.box.cox) {
		parscale<-c(1, 1)
		gamma.start<-3
	} else {
		parscale<-1
		gamma.start<-2
	}
	if(control$use.beta) {
		if(control$use.damping) {
			parscale<-c(parscale, 1e-2, 1e-1)
			gamma.start<-gamma.start+2
		} else {
			parscale<-c(parscale, 1e-2)
			gamma.start<-gamma.start+1
		}
	}
	if(control$length.gamma > 0) {
		parscale<-c(parscale, rep(1e-5, control$length.gamma))	
	}
	
	if((control$p != 0) | (control$q != 0)) {
		parscale<-c(parscale, rep(1e-1, (control$p + control$q)))
	}
	#print(parscale)
	return(parscale)
}

##############################################################################################################################################################################################
##BATS related stuff below
########################################

parameterise<-function(alpha, beta.v=NULL, small.phi=1, gamma.v=NULL, lambda=NULL, ar.coefs=NULL, ma.coefs=NULL) {
	#print("urg")
	#print(lambda)
	if(!is.null(lambda)) {
		param.vector<-cbind(lambda, alpha)
		use.box.cox<-TRUE
	} else {
		#print("hello")
		param.vector<-alpha
		use.box.cox<-FALSE
		#print(use.box.cox)
	}
	if(!is.null(beta.v)) {
		use.beta<-TRUE
			if(is.null(small.phi)) {
				use.damping<-FALSE
			} else if(small.phi != 1) {
				param.vector<-cbind(param.vector, small.phi)
				use.damping<-TRUE
			} else {
				use.damping<-FALSE
			}
		param.vector<-cbind(param.vector, beta.v)
	} else {
		use.beta<-FALSE
		use.damping<-FALSE
	}
	if(!is.null(gamma.v)) {
		gamma.v<-matrix(gamma.v, nrow=1, ncol=length(gamma.v))
		param.vector<-cbind(param.vector, gamma.v)
		length.gamma<-length(gamma.v)
	} else {
		length.gamma<-0
	}
	if(!is.null(ar.coefs)) {
		ar.coefs<-matrix(ar.coefs, nrow=1, ncol=length(ar.coefs))
		param.vector<-cbind(param.vector, ar.coefs)
		p<-length(ar.coefs)
	} else {
		p<-0
	}
	if(!is.null(ma.coefs)) {
		ma.coefs<-matrix(ma.coefs, nrow=1, ncol=length(ma.coefs))
		param.vector<-cbind(param.vector, ma.coefs)
		q<-length(ma.coefs)
	} else {
		q<-0
	}
	#print(use.box.cox)
	control<-list(use.beta=use.beta, use.box.cox=use.box.cox, use.damping=use.damping, length.gamma=length.gamma, p=p, q=q)
	return(list(vect=as.numeric(param.vector), control=control))
}

unParameterise<-function(param.vector, control) {
	#print(control)
	if(control$use.box.cox) {
		lambda<-param.vector[1]
		alpha<-param.vector[2]
		if(control$use.beta) {
			if(control$use.damping) {
				small.phi<-param.vector[3]
				beta<-param.vector[4]
				gamma.start<-5
			} else {
				small.phi<-1
				beta<-param.vector[3]
				gamma.start<-4
			}
		} else {
			small.phi<-NULL
			beta<-NULL
			gamma.start<-3
		}
		if(control$length.gamma > 0) {
			gamma.vector<-param.vector[gamma.start:(gamma.start+control$length.gamma-1)]
			final.gamma.pos<-gamma.start+control$length.gamma-1
		} else {
			gamma.vector=NULL
			final.gamma.pos<-gamma.start-1
		}
		if(control$p != 0) {
			ar.coefs<-param.vector[(final.gamma.pos+1):(final.gamma.pos+control$p)]
		} else {
			ar.coefs<-NULL
		}
		if(control$q != 0) {
			ma.coefs<-param.vector[(final.gamma.pos+control$p+1):length(param.vector)]
		} else {
			ma.coefs<-NULL
		}
	} else {
		lambda<-NULL
		alpha<-param.vector[1]
		if(control$use.beta) {
			if(control$use.damping) {
				small.phi<-param.vector[2]
				beta<-param.vector[3]
				gamma.start<-4
			} else {
				small.phi<-1
				beta<-param.vector[2]
				gamma.start<-3
			}
		} else {
			small.phi<-NULL
			beta<-NULL
			gamma.start<-2
		}
		if(control$length.gamma > 0) {
			gamma.vector<-param.vector[gamma.start:(gamma.start+control$length.gamma-1)]
			final.gamma.pos<-gamma.start+control$length.gamma-1
		} else {
			gamma.vector=NULL
			final.gamma.pos<-gamma.start-1
		}
		if(control$p != 0) {
			ar.coefs<-param.vector[(final.gamma.pos+1):(final.gamma.pos+control$p)]
		} else {
			ar.coefs<-NULL
		}
		if(control$q != 0) {
			ma.coefs<-param.vector[(final.gamma.pos+control$p+1):length(param.vector)]
		} else {
			ma.coefs<-NULL
		}
	}
	return(list(lambda=lambda, alpha=alpha, beta=beta, small.phi=small.phi, gamma.v=gamma.vector, ar.coefs=ar.coefs, ma.coefs=ma.coefs))
}
